home *** CD-ROM | disk | FTP | other *** search
- /*****************************************************************************
- * Sockets routines to handle socket io of objects. *
- * *
- * Written by: Gershon Elber Ver 0.1, June 1993. *
- *****************************************************************************/
-
- #include <stdio.h>
- #include <sys/types.h>
-
- #ifdef __UNIX__
- #if (defined(ultrix) && defined(mips)) || defined(_AIX) || defined(sgi)
- # include <fcntl.h>
- #else
- # include <sys/fcntl.h>
- #endif /* (ultrix && mips) || _AIX || sgi */
- #include <sys/socket.h>
- #if defined(__hpux) || defined(sun)
- # include <sys/file.h>
- #endif /* __hpux || sun */
- #include <netinet/in.h>
- #include <netdb.h>
- #include <errno.h>
- #endif /* __UNIX__ */
-
- #ifdef OS2GCC
- # include <os2.h>
- #endif /* OS2GCC */
-
- #ifdef __WINNT__
- #include <stdlib.h>
- #include <windows.h>
- #include <winsock.h>
- #include <io.h>
- #endif /* __WINNT__ */
-
- #ifdef AMIGA
- #include <string.h>
- #include <exec/types.h>
- #include <exec/ports.h>
- #include <exec/memory.h>
- #include <proto/dos.h>
- #include <proto/exec.h>
- #endif /* AMIGA */
-
- #include "irit_sm.h"
- #include "prsr_loc.h"
- #include "irit_soc.h"
-
- /* #define DEBUG_ECHO */
-
- static void SocketPrintError(char *Str);
- static void SocUnReadChar(int Handler, char c);
- static int SocReadObjPrefix(int Handler);
-
- /*****************************************************************************
- * DESCRIPTION: *
- * IO error print routine. *
- * *
- * PARAMETERS: *
- * Str: To output to stderr as a message. *
- * *
- * RETURN VALUE: *
- * void *
- *****************************************************************************/
- static void SocketPrintError(char *Str)
- {
- # if defined(__UNIX__) || defined(OS2GCC) || defined(AMIGA)
- perror(Str);
- # endif /* __UNIX__ || OS2GCC */
- # ifdef __WINNT__
- fprintf(stderr, "iritserver: %s error %d\n", Str, WSAGetLastError());
- # endif /* __WINNT__ */
- }
-
- /*****************************************************************************
- * DESCRIPTION: M
- * Sets echo printing of read input. M
- * *
- * PARAMETERS: M
- * Handler: The socket info handler index. M
- * EchoInput: TRUE to echo every character read in. M
- * *
- * RETURN VALUE: M
- * void M
- * *
- * KEYWORDS: M
- * SocEchoInput, ipc M
- *****************************************************************************/
- void SocEchoInput(int Handler, int EchoInput)
- {
- _IPStream[Handler].EchoInput = EchoInput;
- }
-
- /*****************************************************************************
- * DESCRIPTION: M
- * Non blocking read of a single character. M
- * Returns EOF if no data is found. M
- * *
- * PARAMETERS: M
- * Handler: The socket info handler index. M
- * *
- * RETURN VALUE: M
- * int: Read character or EOF if none found. M
- * *
- * KEYWORDS: M
- * SocReadCharNonBlock, ipc M
- *****************************************************************************/
- int SocReadCharNonBlock(int Handler)
- {
- int c;
- #ifdef AMIGA
- struct IritMessage *msg;
- #endif /* AMIGA */
-
- if (_IPStream[Handler].UnGetChar >= 0) {
- c = _IPStream[Handler].UnGetChar;
- _IPStream[Handler].UnGetChar = -1;
- return c;
- }
- else if (_IPStream[Handler].BufferPtr < _IPStream[Handler].BufferSize) {
- c = _IPStream[Handler].Buffer[_IPStream[Handler].BufferPtr++];
- return c;
- }
-
- #ifdef OS2GCC
- DosRead(_IPStream[Handler].pipIrit, _IPStream[Handler].Buffer,
- LINE_LEN_LONG, (PULONG) &_IPStream[Handler].BufferSize);
- #endif /* OS2GCC */
- #if defined(__UNIX__) || defined(__WINNT__)
- _IPStream[Handler].BufferSize = recv(_IPStream[Handler].CommuSoc,
- _IPStream[Handler].Buffer,
- LINE_LEN_LONG, 0);
- #endif /* __UNIX__ || __WINNT__ */
- #ifdef AMIGA
- msg = (struct IritMessage *)GetMsg(_IPStream[Handler].CommuSoc);
- if (msg) {
- _IPStream[Handler].BufferSize = msg->nbytes;
- memcpy(_IPStream[Handler].Buffer, msg->txt, msg->nbytes);
- ReplyMsg((struct Message *)msg);
- }else{
- _IPStream[Handler].BufferSize = 0;
- }
- #endif /* AMIGA */
-
- if (_IPStream[Handler].BufferSize > 0) {
- if (_IPStream[Handler].EchoInput) {
- int i;
- unsigned char
- *p = _IPStream[Handler].Buffer;
-
- if (_IPStream[Handler].IsBinary) {
- for (i = 0; i < _IPStream[Handler].BufferSize; i++) {
- if (i % 16 == 0)
- printf("\n%04x: ", i);
- printf("%02x ", *p++);
- }
- printf("\n");
- }
- else
- for (i = 0; i < _IPStream[Handler].BufferSize; i++)
- #if 0 /* if putc is macro, weirdness will occur */
- putc(*p++, stdout);
- #else
- {
- unsigned char tmp = *p++;
- putc(tmp, stdout);
- }
- #endif
- }
- _IPStream[Handler].BufferPtr = 0;
- c = _IPStream[Handler].Buffer[_IPStream[Handler].BufferPtr++];
- }
- else
- c = EOF;
-
- return c;
- }
-
- /*****************************************************************************
- * DESCRIPTION: *
- * Unget one chararacter read from client port. *
- * *
- * PARAMETERS: *
- * Handler: The socket info handler index. *
- * c: Character to unget. *
- * *
- * RETURN VALUE: *
- * void *
- * *
- * KEYWORDS: *
- * SocUnReadChar, ipc *
- *****************************************************************************/
- static void SocUnReadChar(int Handler, char c)
- {
- _IPStream[Handler].UnGetChar = c;
- }
-
- /*****************************************************************************
- * DESCRIPTION: *
- * Gets a single line for syncronization purposes that will prefix an object. *
- * Returns TRUE if prefix found, FALSE otherwise. *
- * *
- * PARAMETERS: *
- * Handler: The socket info handler index. *
- * *
- * RETURN VALUE: *
- * int: TRUE if prefic of object was found, FALSE otherwise *
- *****************************************************************************/
- static int SocReadObjPrefix(int Handler)
- {
- if (_IPStream[Handler].IsBinary) {
- int c;
-
- if ((c = SocReadCharNonBlock(Handler)) != EOF) {
- SocUnReadChar(Handler, (char) c);
- return TRUE;
- }
- }
- else {
- if (SocReadCharNonBlock(Handler) == '[') {
- SocUnReadChar(Handler, '[');
- return TRUE;
- }
- }
-
- return FALSE;
- }
-
- /*****************************************************************************
- * DESCRIPTION: M
- * Non blocking read of a single line. Returns NULL if no line is available. M
- * *
- * PARAMETERS: M
- * Handler: The socket info handler index. M
- * *
- * RETURN VALUE: M
- * char *: Read line, or NULL if unavailable. M
- * *
- * KEYWORDS: M
- * SocReadLineNonBlock, ipc M
- *****************************************************************************/
- char *SocReadLineNonBlock(int Handler)
- {
- static char Line[LINE_LEN_LONG];
- static int
- LineLen = 0;
-
- while (TRUE) {
- int c;
-
- if ((c = SocReadCharNonBlock(Handler)) != EOF) {
- if (c == '\n' || c == '\r') {
- Line[LineLen++] = c;
- Line[LineLen] = 0;
-
- LineLen = 0;
- return Line;
- }
- else if (LineLen >= LINE_LEN_LONG - 1) {
- IritPrsrFatalError("Socket read line too long\n");
- exit(1);
- }
- else {
- Line[LineLen++] = c;
- }
- }
- else
- return NULL;
- }
- }
-
- /*****************************************************************************
- * DESCRIPTION: M
- * Opens the client's socket. Returns handler if succesful. M
- * *
- * PARAMETERS: M
- * BinaryIPC: Do we want to communicate text or binary? M
- * Read: Is this socket for read (TRUE) or write (FALSE). M
- * *
- * RETURN VALUE: M
- * int: Non negative handler if successful, -1 otherwise. M
- * *
- * KEYWORDS: M
- * SocClientCreateSocket, ipc M
- *****************************************************************************/
- int SocClientCreateSocket(int BinaryIPC, int Read)
- {
- int Handler;
- #ifdef AMIGA
- int len;
- char *name, buf[4];
- static int timescalled = 0;
- #endif /* AMIGA */
- #if defined(__UNIX__) || defined(__WINNT__)
- int s;
- char *HostName, *PortNum, HostNameStr[LINE_LEN];
- struct sockaddr_in Sain;
- struct hostent *Host;
- #endif /* __UNIX__ || __WINNT__ */
- #ifdef OS2GCC
- char *Port;
- ULONG rc,
- ulActionTaken, ulFileSize, ulFileAttribute, ulOpenFlag, ulOpenMode;
- #endif /* OS2GCC */
-
- /* Allocate handler. */
- Handler = IritPrsrOpenStreamFromSocket(0, TRUE, BinaryIPC);
-
- #if defined(__UNIX__) || defined(__WINNT__)
- #ifdef __WINNT__
- {
- WSADATA WSAData;
-
- if ((s = WSAStartup(MAKEWORD(1, 1), &WSAData)) != 0 ||
- LOBYTE(WSAData.wVersion) != 1 ||
- HIBYTE(WSAData.wVersion) != 1) {
- fprintf(stderr, "iritserver: WSAStartup: error %d\n",
- WSAGetLastError());
- exit(1);
- }
- }
- #endif
-
- /* Get port address. */
- gethostname(HostNameStr, LINE_LEN);
- if ((HostName = getenv("IRIT_SERVER_HOST")) == NULL)
- HostName = HostNameStr;
-
- if ((Host = gethostbyname(HostName)) == NULL) {
- SocketPrintError("iritclient: hostname unknown\n");
- return -1;
- }
-
- ZAP_MEM(&Sain, sizeof(struct sockaddr_in));
- GEN_COPY(&Sain.sin_addr, Host -> h_addr_list[0], Host -> h_length);
- Sain.sin_family = AF_INET;
-
- if ((PortNum = getenv("IRIT_SERVER_PORT")) != NULL)
- Sain.sin_port = atoi(PortNum);
- else {
- SocketPrintError("iritclient: hostport unknown (set IRIT_SERVER_PORT)\n");
- return -1;
- }
-
- /* Create the socket, make it nonblocking if Read and connect. */
- if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
- SocketPrintError("iritclient: socket");
- return -1;
- }
-
- if (Read) {
- #ifdef __UNIX__
- #ifdef __hpux
- if (fcntl(s, F_SETFL, O_NDELAY) < 0) {
- #else
- if (fcntl(s, F_SETFL, FNDELAY) < 0) {
- #endif /* __hpux */
- SocketPrintError("iritclient: fcntl");
- return -1;
- }
- #endif /* __UNIX__ */
- }
-
- while (connect(s, (struct sockaddr *) &Sain,
- sizeof(struct sockaddr_in)) < 0) {
- # ifdef __UNIX__
- if (errno == EINPROGRESS)
- break;
- # endif /* __UNIX__ */
- # ifdef __WINNT__
- if (WSAGetLastError() == WSAEINPROGRESS)
- break;
- # endif /* __WINNT__ */
- SocketPrintError("iritclient: connect");
- return -1;
- }
-
- _IPStream[Handler].CommuSoc = s;
- #endif /* __UNIX__ || __WINNT__ */
-
- #ifdef OS2GCC
- if ((Port = getenv("IRIT_SERVER_PORT")) == NULL) {
- fprintf(stderr, "No IRIT_SERVER_PORT environment variable, \"\\pipe\\irit_1\" assumed.\n");
- Port = "\\pipe\\irit_1";
- }
-
- DosWaitNPipe(Port, NP_WAIT);
- ulFileSize = 0;
- ulFileAttribute = 0;
- ulOpenFlag = OPEN_ACTION_OPEN_IF_EXISTS;
- ulOpenMode = OPEN_SHARE_DENYNONE | OPEN_ACCESS_READWRITE;
-
- rc = DosOpen(Port,
- &_IPStream[Handler].pipIrit,
- &ulActionTaken,
- ulFileSize,
- ulFileAttribute,
- ulOpenFlag,
- ulOpenMode,
- NULL);
-
- if (rc != 0) {
- DosBeep(1000, 100);
- exit(1);
- }
-
- _IPStream[Handler].CommuSoc = 1;
- #endif /* OS2GCC */
-
- #ifdef AMIGA
- timescalled++;
- if (timescalled % 2) {
- len = GetVar(SERVER_VAR, buf, sizeof(buf), GVF_GLOBAL_ONLY);
- if (len < 0) {
- SocketPrintError
- ("iritclient: cannot get synchronization environment variable");
- return -1;
- }
- DeleteVar(SERVER_VAR, GVF_GLOBAL_ONLY);
- }
-
- name = getenv("IRIT_SERVER_PORT");
- if (!name) {
- SocketPrintError("iritclient: hostport unknown (set IRIT_SERVER_PORT)\n");
- return -1;
- }
- Forbid();
- _IPStream[Handler].CommuSoc = FindPort(name);
- Permit();
- if (!_IPStream[Handler].CommuSoc) {
- SocketPrintError("iritclient: FindPort");
- return -1;
- }
-
- _IPStream[Handler].IsBinary = BinaryIPC;
- buf[0] = '\0';
- if (timescalled % 2) {
- SetVar(CLIENT_VAR, buf, -1, GVF_GLOBAL_ONLY);
- /* This beast busy-waits! Reduce its priority so that we don't hog
- other tasks, namely irit. */
- }
- _IPStream[Handler].oldpri = SetTaskPri(FindTask(0L), -1);
- #endif /* AMIGA */
-
- _IPStream[Handler].IsBinary = BinaryIPC;
-
- return Handler;
- }
-
- /*****************************************************************************
- * DESCRIPTION: M
- * Close the client's socket. M
- * *
- * PARAMETERS: M
- * Handler: The socket info handler index. *
- * *
- * RETURN VALUE: M
- * void M
- * *
- * KEYWORDS: M
- * SocClientCloseSocket, ipc M
- *****************************************************************************/
- void SocClientCloseSocket(int Handler)
- {
- #ifndef AMIGA
- if (_IPStream[Handler].CommuSoc > 0) {
- #else
- if (_IPStream[Handler].CommuSoc != 0) {
- #endif
- #ifdef __UNIX__
- if (close(_IPStream[Handler].CommuSoc) != 0)
- SocketPrintError("iritclient: close");
- #endif /* __UNIX__ */
- #ifdef __WINNT__
- closesocket(_IPStream[Handler].CommuSoc);
- #endif /* __WINNT__ */
- #ifdef OS2GCC
- DosClose(_IPStream[Handler].pipIrit);
- #endif /* OS2GCC */
- #ifdef AMIGA
- SetTaskPri(FindTask(0L), _IPStream[Handler].oldpri);
- #endif /* AMIGA */
-
- _IPStream[Handler].CommuSoc = 0;
- }
- }
-
- /*****************************************************************************
- * DESCRIPTION: M
- * Attempts to read (non blocking) an object from socket. M
- * If read is successful the object is returned, otherwise NULL is returned. M
- * *
- * PARAMETERS: M
- * Handler: The socket info handler index. *
- * *
- * RETURN VALUE: M
- * IPObjectStruct *: An object if read one, NULL otherwise. M
- * *
- * KEYWORDS: M
- * SocReadOneObject, ipc M
- *****************************************************************************/
- IPObjectStruct *SocReadOneObject(int Handler)
- {
- char *ErrorMsg;
- IPObjectStruct *PObj;
-
- #ifndef AMIGA
- if (_IPStream[Handler].CommuSoc > 0 && SocReadObjPrefix(Handler)) {
- #else
- if (_IPStream[Handler].CommuSoc != 0 && SocReadObjPrefix(Handler)) {
- #endif
- IritPrsrSetReadOneObject(TRUE);
-
- if (_IPStream[Handler].IsBinary) {
- PObj = IritPrsrGetBinObject(Handler);
- }
- else {
- PObj = IritPrsrGetObjects(Handler);
- }
- }
- else
- PObj = NULL;
-
- if (IritPrsrParseError(_IPStream[Handler].LineNum, &ErrorMsg)) {
- fprintf(stderr, "Socket: %s\n", ErrorMsg);
- }
-
- return PObj;
- }
-
- /*****************************************************************************
- * DESCRIPTION: M
- * Accept a connection. Must be called by clients at the beginning. M
- * *
- * PARAMETERS: M
- * PrgmInput: A handler to the Program's input channel. M
- * PrgmOutput: A handler to the Program's output channel. M
- * *
- * RETURN VALUE: M
- * int: TRUE, if succesful, FALSE otherwise. M
- * *
- * KEYWORDS: M
- * IritPrsrClntAcceptConnect M
- *****************************************************************************/
- int IritPrsrClntAcceptConnect(int *PrgmInput, int *PrgmOutput)
- {
- static char Line[LINE_LEN];
- int i, Input, Output,
- IsBinary = getenv("IRIT_BIN_IPC") != NULL;
- IPObjectStruct
- *PObj = NULL;
-
- if ((Input = SocClientCreateSocket(IsBinary, TRUE)) >= 0) {
- for (i = 0; i < SOC_TIME_OUT; i++) {
- if ((PObj = SocReadOneObject(Input)) != NULL) {
- if (!IP_IS_STR_OBJ(PObj) ||
- strncmp(PObj -> U.Str, "IRIT_SERVER_PORT=", 17) != 0) {
- IPFreeObject(PObj);
- return FALSE;
- }
- strcpy(Line, PObj -> U.Str);
- IPFreeObject(PObj);
- break;
- }
- IritSleep(10);
- }
- if (i >= SOC_TIME_OUT)
- return FALSE;
- }
- else
- return FALSE;
-
- putenv(Line);
-
- if ((Output = SocClientCreateSocket(IsBinary, FALSE)) < 0)
- return FALSE;
-
- *PrgmInput = Input;
- *PrgmOutput = Output;
-
- return TRUE;
- }
-
- /*****************************************************************************
- * DESCRIPTION: M
- * Close a connection. Must be called by clients at the end. M
- * *
- * PARAMETERS: M
- * PrgmInput: A handler to the Program's input channel. M
- * PrgmOutput: A handler to the Program's output channel. M
- * *
- * RETURN VALUE: M
- * int: TRUE, if succesful, FALSE otherwise. M
- * *
- * KEYWORDS: M
- * IritPrsrClntCloseConnect M
- *****************************************************************************/
- int IritPrsrClntCloseConnect(int PrgmInput, int PrgmOutput)
- {
- SocClientCloseSocket(PrgmInput);
- SocClientCloseSocket(PrgmOutput);
-
- return TRUE;
- }
-